package com.day240701.controller;

import com.alibaba.fastjson2.JSON;
import com.day240701.dao.StudentDao;
import com.day240701.entity.PageInfo;
import com.day240701.entity.Student;
import jdk.nashorn.internal.runtime.ECMAException;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@WebServlet(name = "StudentServlet", value = "/student/manage")
public class StudentServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");

        String op = request.getParameter("op");
        /*
        // 权限控制
        HttpSession session = request.getSession();
        Integer sNo = (Integer) session.getAttribute("sNo");
        // 排除 login这个操作，因为 session中 的sNo 需要 登录后才能 被set 进去
        if(!"login".equals(op)) {
            // 如果 session 中没有 sNo 这个属性，说明没登录成功，跳转到 登录界面
            if(sNo == null) {
                session.setAttribute("msg", "请登录后再访问");
                response.sendRedirect("login.jsp");
                // 中途“截胡”，在后面加了一个 return
                return;// 后续代码就不要执行了
            }
        }*/

        if ("queryAllStudents".equals(op)) { // 查询全部
            queryAllStudents(request, response);
        } else if ("login".equals(op)) { // 登录
            login(request,response);
        } else if ("queryMyInfo".equals(op)) {
            queryMyInfo(request, response);
        } else if ("modifyMyInfo".equals(op)) {
            modifyMyInfo(request,response);
        } else if ("addStudent".equals(op)) {
            addStudent(request, response);
        } else if ("deleteStudentBySNo".equals(op)) {
            deleteStudentBySNo(request, response);
        } else if ("queryStudentInfo".equals(op)) {
            queryStudentInfo(request, response);
        } else if ("modifyStudentInfo".equals(op)) {
            modifyStudentInfo(request, response);
        } else if ("logout".equals(op)) {
            logout(request, response);
        } else if ("admin".equals(op)) {
            admin(request, response);
        } else if ("queryAllStudentsByPage".equals(op)) {
            queryAllStudentsByPage(request, response);
        } else if ("queryAllStudentsByPage2".equals(op)) {
            queryAllStudentsByPage2(request,response);
        } else if ("isSNoExist".equals(op)) {
            isSNoExist(request,response);
        } else if ("queryAllStudentsByPageUsingAjax".equals(op)) {
            queryAllStudentsByPageUsingAjax(request,response);
        }
    }

    protected void queryAllStudents(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        StudentDao studentDao = new StudentDao();
        List<Student> sList = studentDao.queryAllStudents();

        // 交给 专门的 jsp
        // 服务器端 还是 request
        // 打包
        // 全部学生数据不需要一直保存，用 request
        request.setAttribute("sList", sList);
        // 找request调度员 跳转到 jsp
        // 刷新时可以重复查询操作，用转发
        request.getRequestDispatcher("queryAllStudents.jsp").forward(request,response);
    }

    protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String sNoString = request.getParameter("sNo");
        int sNo = 0;
        HttpSession session = request.getSession();
        // 万一转换异常，try-catch 就不报错了，改成回到登录界面，并提示
        try {
            sNo = Integer.parseInt(sNoString); // 判断是否为数字...
        } catch (Exception e) {
            session.setAttribute("msg", "学号不能为非数字，请重新登录！");
            response.sendRedirect("login.jsp");
            return; // 记得 return ！！(后面不需要再执行)
        }


        String password = request.getParameter("password");
        String rememberMe = request.getParameter("rememberMe");

        StudentDao studentDao = new StudentDao();
        boolean flag = studentDao.login(sNo, password);
        if (flag) {
            // 登录成功: 跳转到欢迎界面
            // sNo 学号要长期存在，用 session 保存
            session.setAttribute("sNo", sNo);
            // 体会 转发 与 重定向 的明显表现
            /*request.getRequestDispatcher("main.jsp").forward(request, response);*/
            // 当登陆成功后，将学号密码记录下来
            if ("true".equals(rememberMe)) {
                Cookie sNoCookie = new Cookie("sNo", sNo + "");
                // 补充：我们设置 cookie 存放的路径（path）
//                sNoCookie.setPath("/demo2");
                sNoCookie.setMaxAge(7*24*60*60);

                Cookie passwordCookie = new Cookie("password", password + "");
                passwordCookie.setMaxAge(7*24*60*60);

                Cookie rememberMeCookie = new Cookie("rememberMe", "true");
                rememberMeCookie.setMaxAge(7*24*60*60);

                response.addCookie(sNoCookie);
                response.addCookie(passwordCookie);
                response.addCookie(rememberMeCookie);
            } else {
                // 取消掉
                // 当 cookie name 值 和 浏览器中 旧的 cookie 名字相同就会取代它
                Cookie sNoCookie = new Cookie("sNo", "");
                sNoCookie.setMaxAge(0);

                Cookie passwordCookie = new Cookie("password", "");
                passwordCookie.setMaxAge(0);

                Cookie rememberMeCookie = new Cookie("rememberMe", "");
                rememberMeCookie.setMaxAge(0);

                response.addCookie(sNoCookie);
                response.addCookie(passwordCookie);
                response.addCookie(rememberMeCookie);
            }
            // 登陆成功后，找到 application 对象，然后 webVisitCount+1
            ServletContext application = request.getServletContext();
            // 如果 启动后，第一次登录
            // 网站访问次数
            Integer webVisitCount = (Integer) application.getAttribute("webVisitCount");
            if (webVisitCount == null) {
                webVisitCount = 0;
            }
            webVisitCount++;
            application.setAttribute("webVisitCount", webVisitCount);

            // === === === ===

            // 增加利用 application 实现，记录不同用户ip的访问次数思路：
            // 1.没有存 map 时，初始化，创建 map 对象，并加入该条数据进 map
            // 2.还要再判断 该 ip 有没有访问过吧
            // 最后都要 userVisitCount++ 再塞回去，公共操作

            // 获得用户的 ip 地址
            String userIp = request.getRemoteAddr();
            // 某 ip 访问次数 Map集合
            Map<String,Integer> userVisitCountMap = (Map<String,Integer>) application.getAttribute("userVisitCountMap");

            // 所有用户中，第一次访问网站时
            Integer userVisitCount = null;
            if (userVisitCountMap == null) {
                userVisitCountMap = new HashMap<>();
                userVisitCount = 0;
            } else { // 反之，已经有 map 时
                userVisitCount = userVisitCountMap.get(userIp);
                // 如果该 ip 用户还没访问过，就初始化并添加进 map
                if (userVisitCount == null) {
                    userVisitCount = 0;
                }
            }
            userVisitCount++;
            userVisitCountMap.put(userIp, userVisitCount);
            application.setAttribute("userVisitCountMap", userVisitCountMap);


            // 刷新时重复登录操作没必要，用重定向
            response.sendRedirect("main.jsp");
        } else {
            // 登录失败: 回到登录界面，重新登录
            // 携带相关信息过去
            // 统一用 session 存 msg
            session.setAttribute("msg", "学号或密码错误，请重新登录!");

            //改为 重定向
            response.sendRedirect("login.jsp");
            /*request.getRequestDispatcher("login.jsp").forward(request, response);*/
        }
    }

    protected void queryMyInfo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String sNoString = request.getParameter("sNo");
        int sNo = Integer.parseInt(sNoString);
        StudentDao studentDao = new StudentDao();
        Student my = studentDao.queryMyInfo(sNo);
        HttpSession session = request.getSession();
        session.setAttribute("my", my);
        // 跳转到显示页面
        request.getRequestDispatcher("queryMyInfo.jsp").forward(request, response);
    }

    protected void modifyMyInfo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String sNoString = request.getParameter("sNo");
        int sNo = Integer.parseInt(sNoString);
        String sName = request.getParameter("sName");
        String password = request.getParameter("password");
        String sex = request.getParameter("sex");
        String ageString = request.getParameter("age");
        int age = Integer.parseInt(ageString);

        StudentDao studentDao = new StudentDao();
        Student my = new Student(sNo, sName, password, sex, age, null);
        boolean flag = studentDao.modifyStudent(my);
        HttpSession session = request.getSession();
        if (flag) {
            session.setAttribute("msg", "修改成功");
            session.setAttribute("my", my);
        } else {
            session.setAttribute("msg", "修改失败");
        }

        // 修改 刷新时不需要重复操作，改为 重定向
        /*request.getRequestDispatcher("student?op=queryMyInfo&sNo=" + sNo).forward(request, response);*/
        response.sendRedirect("queryMyInfo.jsp");
    }

    protected void addStudent(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String sName = request.getParameter("sName");
        String password = request.getParameter("password");
        String sex = request.getParameter("sex");
        String ageString = request.getParameter("age");
        int age= Integer.parseInt(ageString);

        Student newStudent = new Student(0, sName, password, sex, age, null);
        StudentDao studentDao = new StudentDao();
        boolean flag = studentDao.addStudent(newStudent);
        HttpSession session = request.getSession();
        if (flag) {
            session.setAttribute("msg", "添加成功");
            // 测试结果：直接到 jsp 页面会报错
            /*request.getRequestDispatcher("queryAllStudents.jsp").forward(request, response);*/ // 思考：是直接到 jsp 页面吗？还是先到 servlet 中的 queryAllStudent?
//            request.getRequestDispatcher("manage?op=queryAllStudents").forward(request, response);
            response.sendRedirect("manage?op=queryAllStudents");
        } else {
            session.setAttribute("msg", "添加失败");
            // 同理，思考这里地址应该用什么？
            //  -> 测试结果：直接到 jsp 就可以
            // 发现问题：不是登录状态（直接地址栏输入）也能直接访问 addStudent.jsp 页面
//            request.getRequestDispatcher("addStudent.jsp").forward(request, response);
            response.sendRedirect("addStudent.jsp");
        }
    }

    protected void deleteStudentBySNo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String sNoString = request.getParameter("sNo");
        int sNo = Integer.parseInt(sNoString);

        StudentDao studentDao = new StudentDao();
        boolean flag = studentDao.deleteStudentBySNo(sNo);
        HttpSession session = request.getSession();
        if (flag) {
            session.setAttribute("msg", "删除成功");
//            request.getRequestDispatcher("manage?op=queryAllStudents").forward(request, response);
        } else {
            session.setAttribute("msg", "删除失败");
//            request.getRequestDispatcher("manage?op=queryAllStudents").forward(request, response);
        }
        response.sendRedirect("manage?op=queryAllStudents");
    }

    protected void queryStudentInfo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String sNoString = request.getParameter("sNo");
        int sNo = Integer.parseInt(sNoString);
        StudentDao studentDao = new StudentDao();
        Student stu = studentDao.queryMyInfo(sNo);
        request.setAttribute("stu", stu);

        request.getRequestDispatcher("modifyStudent.jsp").forward(request, response);
    }

    protected void modifyStudentInfo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String sNoString = request.getParameter("sNo");
        int sNo = Integer.parseInt(sNoString);
        String sName = request.getParameter("sName");
        String password = request.getParameter("password");
        String sex = request.getParameter("sex");
        String ageString = request.getParameter("age");
        int age = Integer.parseInt(ageString);

        StudentDao studentDao = new StudentDao();
        Student stu = new Student(sNo, sName, password, sex, age, null);
        boolean flag = studentDao.modifyStudent(stu);
        HttpSession session = request.getSession();
        if (flag) {
            session.setAttribute("msg", "修改成功");
//            request.getRequestDispatcher("manage?op=queryAllStudents").forward(request, response);
            response.sendRedirect("manage?op=queryAllStudents");
        } else {
            session.setAttribute("msg", "修改失败");
//            request.getRequestDispatcher("manage?op=queryStudentInfo&sNo=" + sNo).forward(request, response);
            response.sendRedirect("manage?op=queryStudentInfo&sNo=" + sNo);
        }

    }

    protected void logout(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        session.removeAttribute("sNo"); // 只是 移除了 session 对象中的某个属性

        // 用于使得当前的HTTP会话失效。当调用这个方法后，会话对象会被标记为已失效，但是直到HTTP响应被完全发送出去后，会话才会被销毁。
        //session.invalidate(); // 销毁 删除了 session 对象
        //session.setMaxInactiveInterval(10); // 多久没有活动就会销毁掉

        // session 已经被销毁了，所以不能直接用了
        //session.setAttribute("msg", "登出成功，请重新登录");
        response.sendRedirect("login.jsp");
    }

    protected void admin(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("admin.jsp").forward(request, response);
    }

    protected void queryAllStudentsByPage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int pageIndex = 1; // 默认第一页
        int pageSize = 5; // 默认一页5条
        String pageIndexString = request.getParameter("pageIndex");
        String pageSizeString = request.getParameter("pageSize");

        try {
            pageIndex = Integer.parseInt(pageIndexString);
        } catch (Exception e) {
            System.out.println("传入的是非数字，pageIndex默认为1");
        }
        try {
            pageSize = Integer.parseInt(pageSizeString);
        } catch (Exception e) {
            System.out.println("传入的是非数字，pageSize默认为5");
        }

        StudentDao studentDao = new StudentDao();
        // 升级：不仅仅是获得分页数据，还要获得 一些相关参数  并返回到页面（jsp）中
        List<Student> sList = studentDao.queryAllStudentsByPage(pageIndex, pageSize);
        // 总条数
        int totalDataNum = studentDao.queryAllStudentsByPage_count();
        // 总页数
        int totalPageNum = totalDataNum/pageSize + ((totalDataNum%pageSize == 0) ? 0 : 1); // 当总页数 不能被 一页几条整除时 +1

        PageInfo<Student> pageInfo = new PageInfo<>();
        pageInfo.setPageIndex(pageIndex);
        pageInfo.setPageSize(pageSize);
        pageInfo.setTotalPageNum(totalPageNum);
        pageInfo.setTotalDataNum(totalDataNum);
        pageInfo.setData(sList);

//        request.setAttribute("sList", sList);
        request.setAttribute("pageInfo", pageInfo);

        request.getRequestDispatcher("queryAllStudentsByPage.jsp").forward(request, response);
    }
    protected void queryAllStudentsByPage2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int pageIndex = 1; // 默认第一页
        int pageSize = 5; // 默认一页5条
        String pageIndexString = request.getParameter("pageIndex");
        String pageSizeString = request.getParameter("pageSize");

        try {
            pageIndex = Integer.parseInt(pageIndexString);
        } catch (Exception e) {
            System.out.println("传入的是非数字，pageIndex默认为1");
        }
        try {
            pageSize = Integer.parseInt(pageSizeString);
        } catch (Exception e) {
            System.out.println("传入的是非数字，pageSize默认为5");
        }


        String sNo = request.getParameter("sNo");
        String sName =  request.getParameter("sName");
        String sex =  request.getParameter("sex");
        String age =  request.getParameter("age");

        if (sNo == null || "".equals(sNo)) {
            sNo = "%%";
        }
        if (sName == null || "".equals(sName)) {
            sName = "%%";
        }else {
            sName = "%" + sName + "%";
        }
        if (sex == null || "".equals(sex)) {
            sex = "%%";
        }
        if (age == null || "".equals(age)) {
            age = "%%";
        }
        StudentDao studentDao = new StudentDao();


        List<Student> sList = studentDao.queryAllStudentsByPage2(sNo, sName, sex, age, pageIndex, pageSize);
        // 总条数
        int totalDataNum = studentDao.queryAllStudentsByPage2_count(sNo, sName, sex, age);
        // 总页数
        int totalPageNum = totalDataNum/pageSize + ((totalDataNum%pageSize == 0) ? 0 : 1); // 当总页数 不能被 一页几条整除时 +1

        PageInfo<Student> pageInfo = new PageInfo<>();
        pageInfo.setPageIndex(pageIndex);
        pageInfo.setPageSize(pageSize);
        pageInfo.setTotalPageNum(totalPageNum);
        pageInfo.setTotalDataNum(totalDataNum);
        pageInfo.setData(sList);

        request.setAttribute("pageInfo", pageInfo);

        request.getRequestDispatcher("queryAllStudentsByPage2.jsp").forward(request, response);
    }
    protected void isSNoExist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String sNoString  =   request.getParameter("sNo");
        int sNo  = Integer.parseInt(sNoString);
        StudentDao studentDao  = new StudentDao();
        boolean flag  =  studentDao.isSNoExist(sNo);

        PrintWriter out = response.getWriter();
        out.println(flag);
        out.flush();
        out.close();
    }

    protected void queryAllStudentsByPageUsingAjax(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int pageIndex = 1; // 默认第一页
        int pageSize = 5; // 默认一页5条
        String pageIndexString = request.getParameter("pageIndex");
        String pageSizeString = request.getParameter("pageSize");

        try {
            pageIndex = Integer.parseInt(pageIndexString);
        } catch (Exception e) {
            System.out.println("传入的是非数字，pageIndex默认为1");
        }
        try {
            pageSize = Integer.parseInt(pageSizeString);
        } catch (Exception e) {
            System.out.println("传入的是非数字，pageSize默认为5");
        }

        String sNo = request.getParameter("sNo");
        String sName =  request.getParameter("sName");
        String sex =  request.getParameter("sex");
        String age =  request.getParameter("age");

        if (sNo == null || "".equals(sNo)) {
            sNo = "%%";
        }
        if (sName == null || "".equals(sName)) {
            sName = "%%";
        }else {
            sName = "%" + sName + "%";
        }
        if (sex == null || "".equals(sex)) {
            sex = "%%";
        }
        if (age == null || "".equals(age)) {
            age = "%%";
        }

        StudentDao studentDao = new StudentDao();

        /*List<Student> sList = studentDao.queryAllStudentsByPage(pageIndex, pageSize);
        // 总条数
        int totalDataNum = studentDao.queryAllStudentsByPage_count();*/

        List<Student> sList = studentDao.queryAllStudentsByPage2(sNo,sName,sex,age,pageIndex,pageSize);
        //总条数
        int totalDataNum = studentDao.queryAllStudentsByPage2_count(sNo,sName,sex,age);
        // 总页数
        int totalPageNum = totalDataNum/pageSize + ((totalDataNum%pageSize == 0) ? 0 : 1); // 当总页数 不能被 一页几条整除时 +1

        PageInfo<Student> pageInfo = new PageInfo<>();
        pageInfo.setPageIndex(pageIndex);
        pageInfo.setPageSize(pageSize);
        pageInfo.setTotalPageNum(totalPageNum);
        pageInfo.setTotalDataNum(totalDataNum);
        pageInfo.setData(sList);


        String str = JSON.toJSONString(pageInfo);
        PrintWriter out = response.getWriter();
        out.println(str);
        out.flush();
        out.close();
    }
}
